"""
1. 什么是高阶函数和闭包并举例说明。

参数有函数的函数是高阶
返回结果是函数的函数是高阶函数


内层函数引用到了外层函数的自由变量，就是闭包
"""


# 高阶函数
def fn1(a):
    a


def a():
    print("高阶函数")


fn1(a())


# 闭包
def fn2():
    b = 1

    def fn3():
        print(b)

    return fn3


fn2()()
"""
2. 请列出functools包内的每个函数的功能作用。

常用方法有
1、functools.partial(func, *args, **keywords): 这个函数用于固定部分参数，生成新的函数，也就是偏函数。例如，如果你有一个函数f(a, b, c)，你可以创建一个新的函数g = functools.partial(f, a=1)，这样调用g(b, c)就相当于调用f(1, b, c)。
2、functools.reduce(function, iterable[, initializer]): 这个函数用于对可迭代对象进行累积操作。例如，functools.reduce(lambda x, y: x*y, [1, 2, 3, 4, 5])会计算((((1*2)*3)*4)*5)，结果是120。
3、functools.lru_cache(maxsize=128, typed=False): 这个装饰器可以用于函数，它会将函数的结果缓存起来，当函数再次被相同的参数调用时，直接返回缓存的结果，而不是重新计算。这对于计算量大，但结果不变的函数非常有用。
4、functools.wraps(wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES): 这个函数用于装饰器内部，它可以保持被装饰函数的元信息，如函数名，文档字符串等。
5、functools.update_wrapper(wrapper, wrapped, assigned=WRAPPER_ASSIGNMENTS, updated=WRAPPER_UPDATES)：以函数的方式来装饰函数信息的

3. 请使用已学习的装饰器相关知识自己实现functools.lru_cache。
"""
from functools import wraps

cache = dict()


# 仿写lru_cache
def lru_cache():
    def foo(fn):
        @wraps(fn)
        def wrapper(i, *args, **kwargs):
            res = cache.get(i)
            if not res:
                res = fn(i, *args, **kwargs)
                cache[i] = res
            return res

        return wrapper

    return foo


# 在生成斐波那契数列中使用缓存，效果非常明显
@lru_cache()
def fib(i):
    if i == 0:
        return 0
    elif i == 1:
        return 1
    return fib(i - 1) + fib(i - 2)


print(fib(400))

"""
4. 什么是类型注解并说明其背后的目的。

类型注解允许开发者为变量、函数参数、函数返回值指定预期的数据类型。并不会影响Python的运行时行为，Python仍然是一门动态类型的语言。
类型注解的语法如下：

def greet(name: str) -> str:
    return 'Hello, ' + name
    
在这个例子中，name: str 是一个类型注解，表示参数 name 应该是一个字符串。-> str 是另一个类型注解，表示函数 greet 的返回值应该是一个字符串。
类型注解背后的目的主要有以下几点：
1、提高代码可读性：通过类型注解，其他开发者可以更容易地理解函数的预期输入和输出。
2、辅助开发工具：许多IDE和编辑器可以利用类型注解提供更准确的代码补全、提示和错误检查。
3、静态类型检查：虽然Python本身不会对类型注解进行检查，但我们可以使用如mypy等第三方工具对代码进行静态类型检查，从而在运行代码之前就发现潜在的类型错误。
需要注意的是，类型注解并不是强制的，也不会影响代码的运行。
"""
